package com.fiveflavors.suittar.growl;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import com.fiveflavors.suittar.gui.utils.Converter;

import twitter4j.Status;

public class GrowlHelper {

	private static long currentDateTime = 0L;
	private static long currentStatusId = 0L;
	
	public static boolean checkGrowlSupport() {
		
		//Checking OS Name
		String osName = System.getProperty("os.name").toLowerCase();
		if (osName.indexOf("mac") < 0) {
			return false;
		}
		
		//Checking AppleScript (/usr/bin/osascript) existing
		File osascript = new File("/usr/bin/osascript");
		if (!osascript.exists()) {
			return false;
		}
		
		//Checking Growl executed.
		String[] command = new String[] {
				"/usr/bin/osascript",
				"-e",
				"tell application \"System Events\"",
				"-e",
				"set isRunning to count of (every process whose name is \"GrowlHelperApp\")",
				"-e",
				"end tell"
		};	
		try {
			String growlCnt = operateAppleScript(command);
			if (growlCnt == null || growlCnt.length() == 0) {
				return false;
			}
			return (Integer.parseInt(growlCnt)) > 0;
		}
		catch(NumberFormatException e) {
			return false;
		}
	}
	
	public static void notifyTimeLine2Growl(List<Status> statusList,boolean show) {
		
		TreeSet<Status> growlStatusSet = new TreeSet<Status>(
				new Comparator<Status>(){
					public int compare(Status o1,Status o2) {
						long dateTime1 = Converter.convertUTCString2JSTDate(o1.getCreatedAt()).getTime();
						long dateTime2 = Converter.convertUTCString2JSTDate(o2.getCreatedAt()).getTime();
						long statusId1 = o1.getId();
						long statusId2 = o2.getId();
						//逆ソート
						if (statusId1 < statusId2 || dateTime1 < dateTime2) {
							return -1;
						}
						else if (statusId1 == statusId2 && dateTime1 == dateTime2) {
							return 0;
						}
						return 1;
					}
		});
		
		for (Status status: statusList) {
			long dateTime = Converter.convertUTCString2JSTDate(status.getCreatedAt()).getTime();
			long statusId = status.getId();
			if (statusId > currentStatusId || dateTime > currentDateTime) {
				growlStatusSet.add(status);
			}
		}
		
		for (Status status: growlStatusSet) {
			if (show) {
				notify2Growl(status);				
			}
			currentStatusId = status.getId();
			currentDateTime = Converter.convertUTCString2JSTDate(status.getCreatedAt()).getTime();
		}
	}
	
	private static void notify2Growl(Status status) {
		String title = status.getUser().getScreenName() + " " + Converter.convertUTCString2JSTString(status.getCreatedAt());
		String description = status.getText();
		String[] command = new String[] {
				"/usr/bin/osascript",
				"-e",
				"tell application \"GrowlHelperApp\"",
				"-e",
				"set the allNotificationsList to {\"Friends Timeline\"}",
				"-e",
				"set the enabledNotificationsList to {\"Friends Timeline\"}",
				"-e",
				"register as application \"Suittar!\" " +
				"all notifications allNotificationsList default notifications enabledNotificationsList",
				"-e",
				"notify with name \"Friends Timeline\" title \"" + title + "\" description \"" + description + "\" application name \"Suittar!\"",
				"-e",
				"end tell"
		};
		operateAppleScript(command);
	}
	
	private static String operateAppleScript(String[] command) {
		try {
			ProcessBuilder pb = new ProcessBuilder(command);
			pb.redirectErrorStream(true);
			Process process = pb.start();
			
			TempBufferedReader reader = new TempBufferedReader(process.getInputStream());
			reader.start();
			process.waitFor();
			reader.close();
			
			return reader.getStdOut();			
		}
		catch(Exception e) {
			return null;
		}
	}
	
	static class TempBufferedReader extends Thread {
		
		InputStream is = null;
		StringBuffer stdOut = new StringBuffer();
		
		public TempBufferedReader(InputStream is) {
			this.is = is;
		}
		
		public void run() {
			
			if (is != null) {
				BufferedReader reader = new BufferedReader(new InputStreamReader(is));
				try {
					String st = null;
					while((st = reader.readLine()) != null) {
						stdOut.append(st);
					}				
				}
				catch (IOException e) {				
				}				
			}
		}
		
		public void close() throws IOException {
			if (is != null) {
				is.close();
			}
		}
		
		public String getStdOut() {
			return stdOut.toString();
		}
	}
		
}

